package com.jin.lazytool.customevent;

import com.jin.lazytool.componment.NumberField;
import com.jin.lazytool.entity.IEvent;
import com.jin.lazytool.entity.ILoopEvent;
import com.jin.lazytool.entity.LoopEndEvent;
import com.jin.lazytool.entity.LoopStartEvent;
import com.jin.lazytool.utils.JinUtils;
import com.jin.lazytool.utils.JsonUtils;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.GridPane;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.SimpleFormatter;

public abstract class CustomEvent {

    protected final NumberField time = new NumberField();

    protected final TextArea luaScript = new TextArea();

    protected Button luaButton = new Button("LUA脚本");
    {
        Tooltip.install(luaButton, new Tooltip("""
                返回对象
                {
                    exeFlag: true, // 是否执行        必须返回
                    time: 0,       // 执行前等待时间  必须返回
                    ...            // 可编辑字段
                }"""));

        luaScript.setPromptText("""
                    function jin(time)\r
                        -- doing something \r
                        local obj = {} \r
                        obj.exeFlag = false \r
                        obj.time = time \r
                        ... \r
                        return obj\r
                    end\r
                """);
        // 设置鼠标进入事件处理器
        luaButton.setOnMouseEntered((event)-> luaButton.getStyleClass().add("hand-cursor"));

        // 设置鼠标移出事件处理器
        luaButton.setOnMouseExited((event)-> luaButton.getStyleClass().remove("hand-cursor"));

        luaButton.setOnAction(event -> {
            if(luaScript.getText() == null || "".equals(luaScript.getText())){
                return;
            }
            try {
                LuaTable table = JinUtils.evalLua(luaScript.getText(), -1);

                LuaValue[] keys = table.keys();
                Map<Object,Object> map = new HashMap<>();
                for (LuaValue key : keys) {
                    LuaValue val = table.get(key);
                    Object ov = null;
                    if(val.isboolean()){
                        ov = val.toboolean();
                    }else if(val.isint()){
                        ov = val.toint();
                    }else if(val.islong()){
                        ov = val.tolong();
                    }else if(val.isnumber()){
                        ov = val.tonumber();
                    }else {
                        ov = val.toString();
                    }
                    map.put(key.toString(),ov);
                }
                JinUtils.alert(JsonUtils.toJson(map));
            }catch (Exception e){
                LogRecord lr = new LogRecord(Level.SEVERE, "执行脚本异常");
                lr.setThrown(e);
                SimpleFormatter simpleFormatter = new SimpleFormatter();
                String format = simpleFormatter.format(lr);
                JinUtils.getDialog("执行脚本异常",(grid,dialog)->{
                    grid.getColumnConstraints().remove(1);
                    grid.getColumnConstraints().remove(0);
                    grid.setPrefHeight(500);
                    grid.setPrefWidth(1000);
                    TextArea textArea = new TextArea(format);
                    textArea.setPrefHeight(500);
                    textArea.setPrefWidth(1000);
                    textArea.setEditable(false);
                    grid.addRow(grid.getRowCount(),textArea);
                },()->{});
            }

        });
    }

    public static void main(String[] args) {
        LuaTable table = JinUtils.evalLua("""
                function jin(time)
                    -- doing something
                    local obj = {}
                    obj.exeFlag = false
                    obj.time = time
                    return obj
                end
                """ , -1);

        LuaValue[] keys = table.keys();
        Map<Object,Object> map = new HashMap<>();
        for (LuaValue key : keys) {
            LuaValue val = table.get(key);
            Object ov = null;
            if(val.isboolean()){
                ov = val.toboolean();
            }else if(val.isint()){
                ov = val.toint();
            }else if(val.islong()){
                ov = val.tolong();
            }else if(val.isnumber()){
                ov = val.tonumber();
            }else {
                ov = val.toString();
            }
            map.put(key.toString(),ov);
        }
        System.out.println(JsonUtils.toJson(map));

    }
    public static final ArrayList<CustomEvent> CUSTOM_EVENTS = new ArrayList<>();
    public static final Map<Class<? extends IEvent>,CustomEvent> CUSTOM_EVENTS_MAP = new HashMap<>();

    public static final Map<String,IEvent[]> LOOP_EVENTS = new HashMap<>();


    public static void addLoopEvent( IEvent event){
        ILoopEvent iLoopEvent = (ILoopEvent)event;
        IEvent[] iEvents = LOOP_EVENTS.computeIfAbsent(iLoopEvent.getLoopNum(), k -> new IEvent[2]);
        if(event instanceof LoopStartEvent){
            iEvents[0] = event;
        }else if(event instanceof LoopEndEvent){
            iEvents[1] = event;
        }
    }
    public static void removeLoopEvent(IEvent event){
        if(event instanceof ILoopEvent){
            ILoopEvent iLoopEvent = (ILoopEvent)event;
            IEvent[] iEvents = LOOP_EVENTS.get(iLoopEvent.getLoopNum());
            if(iEvents != null){
                if(event instanceof LoopStartEvent){
                    iEvents[0] = null;
                }else if(event instanceof LoopEndEvent){
                    iEvents[1] = null;
                }
            }
        }
    }

    public static List<String> getNoOverLoopEvent(){
        List<String> loopNums = new ArrayList<>();
        for (String loopNum : LOOP_EVENTS.keySet()) {
            IEvent[] iEvents = LOOP_EVENTS.get(loopNum);
            if(iEvents != null && iEvents[1] == null){
                loopNums.add(loopNum);
            }
        }
        return loopNums;
    }

    public static void registerCustomEvent(CustomEvent customEvent){
        CUSTOM_EVENTS.add(customEvent);
        CUSTOM_EVENTS_MAP.put(customEvent.eventClass(),customEvent);
    }
    public abstract String getName();
    public abstract void initAddPanel(GridPane grid);
    public abstract void initEditPanel(GridPane grid,IEvent event);
    public abstract IEvent fullAddIEvent();
    public abstract void fullEditIEvent();

    abstract Class<? extends IEvent> eventClass();

    public static CustomEvent initEditPane(GridPane grid, IEvent event){
        CustomEvent customEvent = CUSTOM_EVENTS_MAP.get(event.getClass());
        customEvent.initEditPanel(grid,event);
        return customEvent;
    }
}
